import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;

import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.swing.*;
import java.io.*;
import java.sql.*;
import java.util.*;
import java.awt.*;
import java.awt.image.*;
import com.sun.image.codec.jpeg.*;


public class TwoWaySerialComm
{
	static String getValue=null;

	protected BufferedImage img1 = null;
	protected BufferedImage img2 = null;
	protected BufferedImage imgc = null;
	protected int comparex = 0;
	protected int comparey = 0;
	protected int factorA = 0;
	protected int factorD = 10;
	protected boolean match = false;
	protected int debugMode = 0; // 1: textual indication of change, 2: difference of factors

	/* create a runable demo thing. */
	public static void main(String[] args) {
		// Create a compare object specifying the 2 images for comparison.
	
		 try
	        {
	            (new TwoWaySerialComm()).connect("COM46","COM53");
	          // (new TwoWaySerialComm()).connect1("COM53");
	        }
	        catch ( Exception e )
	        {
	            // TODO Auto-generated catch block
	            e.printStackTrace();
	        }
		
		// If its not a match then write a file to show changed regions.
		
	}
	
	// constructor 1. use filenames
	public TwoWaySerialComm(String file1, String file2) {
		this(loadJPG(file1), loadJPG(file2));
	}
 
	// constructor 2. use awt images.
	public TwoWaySerialComm(Image img1, Image img2) {
		this(imageToBufferedImage(img1), imageToBufferedImage(img2));
	}
 
	// constructor 3. use buffered images. all roads lead to the same place. this place.
	public TwoWaySerialComm(BufferedImage img1, BufferedImage img2) {
		this.img1 = img1;
		this.img2 = img2;
		autoSetParameters();
	}

	// like this to perhaps be upgraded to something more heuristic in the future.
	protected void autoSetParameters() {
		comparex = 10;
		comparey = 10;
		factorA = 10;
		factorD = 10;
	}
	
	// set the parameters for use during change detection.
	public void setParameters(int x, int y, int factorA, int factorD) {
		this.comparex = x;
		this.comparey = y;
		this.factorA = factorA;
		this.factorD = factorD;
	}
	
	// want to see some stuff in the console as the comparison is happening?
	public void setDebugMode(int m) {
		this.debugMode = m;
	}
	
	// compare the two images in this object.
	public void compare() {
		// setup change display image
		imgc = imageToBufferedImage(img2);
		Graphics2D gc = imgc.createGraphics();
		gc.setColor(Color.RED);
		// convert to gray images.
		img1 = imageToBufferedImage(GrayFilter.createDisabledImage(img1));
		img2 = imageToBufferedImage(GrayFilter.createDisabledImage(img2));
		// how big are each section
		int blocksx = (int)(img1.getWidth() / comparex);
		int blocksy = (int)(img1.getHeight() / comparey);
		// set to a match by default, if a change is found then flag non-match
		this.match = true;
		// loop through whole image and compare individual blocks of images
		for (int y = 0; y < comparey; y++) {
			if (debugMode > 0) System.out.print("|");
			for (int x = 0; x < comparex; x++) {
				int b1 = getAverageBrightness(img1.getSubimage(x*blocksx, y*blocksy, blocksx - 1, blocksy - 1));
				int b2 = getAverageBrightness(img2.getSubimage(x*blocksx, y*blocksy, blocksx - 1, blocksy - 1));
				int diff = Math.abs(b1 - b2);
				if (diff > factorA) { // the difference in a certain region has passed the threshold value of factorA
					// draw an indicator on the change image to show where change was detected.
					gc.drawRect(x*blocksx, y*blocksy, blocksx - 1, blocksy - 1);
					this.match = false;
				}
				if (debugMode == 1) System.out.print((diff > factorA ? "X" : " "));
				if (debugMode == 2) System.out.print(diff + (x < comparex - 1 ? "," : ""));
			}
			if (debugMode > 0) System.out.println("|");
		}
	}
	
	// return the image that indicates the regions where changes where detected.
	public BufferedImage getChangeIndicator() {
		return imgc;
	}
	
	// returns a value specifying some kind of average brightness in the image.
	protected int getAverageBrightness(BufferedImage img) {
		Raster r = img.getData();
		int total = 0;
		for (int y = 0; y < r.getHeight(); y++) {
			for (int x = 0; x < r.getWidth(); x++) {
				total += r.getSample(r.getMinX() + x, r.getMinY() + y, 0);
			}
		}
		return (int)(total / ((r.getWidth()/factorD)*(r.getHeight()/factorD)));
	}
	

	// returns true if image pair is considered a match
	public boolean match() {
		return this.match;
	}

	// buffered images are just better.
	protected static BufferedImage imageToBufferedImage(Image img) {
		BufferedImage bi = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_RGB);
		Graphics2D g2 = bi.createGraphics();
		g2.drawImage(img, null, null);
		return bi;
	}
	
	// write a buffered image to a jpeg file.
	protected static void saveJPG(Image img, String filename) {
		BufferedImage bi = imageToBufferedImage(img);
		FileOutputStream out = null;
		try { 
			out = new FileOutputStream(filename);
		} catch (java.io.FileNotFoundException io) { 
			System.out.println("File Not Found"); 
		}
		JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
		JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bi);
		param.setQuality(0.8f,false);
		encoder.setJPEGEncodeParam(param);
		try { 
			encoder.encode(bi); 
			out.close(); 
		} catch (java.io.IOException io) {
			System.out.println("IOException"); 
		}
	}
	
	// read a jpeg file into a buffered image
	protected static Image loadJPG(String filename) {
		FileInputStream in = null;
		try { 
			in = new FileInputStream(filename);
		} catch (java.io.FileNotFoundException io) { 
			System.out.println("File Not Found"); 
		}
		JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(in);
		BufferedImage bi = null;
		try { 
			bi = decoder.decodeAsBufferedImage(); 
			in.close(); 
		} catch (java.io.IOException io) {
			System.out.println("IOException");
		}
		return bi;
	}

    public TwoWaySerialComm()
    {
        super();
    }
  
    
    void connect ( String portName,String portName1 ) throws Exception
    {
        CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
        CommPortIdentifier portIdentifier1 = CommPortIdentifier.getPortIdentifier(portName1);
        if ( portIdentifier.isCurrentlyOwned() )
        {
            System.out.println("Error: Port is currently in use");
        }
        else
        {
            CommPort commPort = portIdentifier.open(this.getClass().getName(),2000);
            CommPort commPort1 = portIdentifier1.open(this.getClass().getName(),2000);
            
            if ( commPort instanceof SerialPort )
            {
                SerialPort serialPort = (SerialPort) commPort;
                serialPort.setSerialPortParams(9600,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
                SerialPort serialPort1 = (SerialPort) commPort1;
                serialPort1.setSerialPortParams(9600,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
                
                InputStream in = serialPort.getInputStream();
                OutputStream out = serialPort.getOutputStream();
                OutputStream out1 = serialPort1.getOutputStream();
                
                (new Thread(new SerialReader(in,out,out1))).start();
               // (new Thread(new SerialWriter(out))).start();

            }
            else
            {
                System.out.println("Error: Only serial ports are handled by this example.");
            }
        }     
    }
    
    
    /** */
    public static class SerialReader implements Runnable 
    {
        InputStream in;
		OutputStream out;
		OutputStream out1;
        
        public SerialReader ( InputStream in,OutputStream out,OutputStream out1 )
        {
            this.in = in;
            this.out = out; 
            this.out1 = out1;
        }
        
        
        public void run ()
        {
            byte[] buffer = new byte[1024];
            int len = -1,coumt=0;
            
            try
            {
                while ( ( len = this.in.read(buffer)) > -1 )
                {	
                      System.out.print(new String(buffer,0,len));      
                      String d = new String(buffer,49,len);
              		//buffer=null;
                     
                try
                {       
        		    
                	if(coumt==0)
                	{
                    this.out.write('A');
                    this.out.write('T');
                    this.out.write('+');
                    this.out.write('C');
                    this.out.write('N');
                    this.out.write('M');
                    this.out.write('I');
                    this.out.write('=');
                    this.out.write('1');
                    this.out.write(',');
                    this.out.write('2');
                    this.out.write(',');
                    this.out.write('0');
                    this.out.write(',');
                    this.out.write('0');
                    this.out.write(0X0D);
                    this.out.write(0X0a);
                    coumt=2;
                	}
                	TwoWaySerialComm ic = new TwoWaySerialComm("c:\\test1.jpg", "c:\\test2.jpg");
            		// Set the comparison parameters. 
            		//   (num vertical regions, num horizontal regions, sensitivity, stabilizer)
            		ic.setParameters(8, 6, 5, 10);
            		// Display some indication of the differences in the image.
            		ic.setDebugMode(2);
            		// Compare.
            		ic.compare();
            		// Display if these images are considered a match according to our parameters.
            		System.out.println("Match: " + ic.match());
            		int c = 0;
            		    if(ic.match()==false)
                        {
                        	System.out.println("Image Not Regozined");
                            this.out.write('A');
                            this.out.write('T');
                            this.out.write('+');
                            this.out.write('C');
                            this.out.write('M');
                            this.out.write('G');
                            this.out.write('S');
                            this.out.write('=');
                            this.out.write('"');
                            this.out.write('+');
                            this.out.write('9');
                            this.out.write('1');
                            this.out.write('8');
                            this.out.write('0');
                            this.out.write('1');
                            this.out.write('5');
                            this.out.write('3');
                            this.out.write('3');
                            this.out.write('5');
                            this.out.write('4');
                            this.out.write('6');
                            this.out.write('2');
                            this.out.write('"');
                            this.out.write(0X0a);
                            this.out.write(0X0D);

                            this.out.write('A');
                            this.out.write('L');
                            this.out.write('E');
                            this.out.write('R');
                            this.out.write('T');
                            this.out.write('!');
                            this.out.write('!');
                            this.out.write('!');
                            this.out.write(26);

                      		try {
                          	    Thread.sleep(6000);
                          	} catch(InterruptedException ex) {
                          	    Thread.currentThread().interrupt();
                          	}

                      		
                            coumt=0;
                        } 
            		    
            		    
            		    if(d!=null)
                        {
            		    	
                      	  if(d.startsWith("OFF"))
            		    {System.out.println("Light Off");//.substring(54, 57));}
            		    this.out1.write('R');
            		    }
                      	  
                      	if(d.startsWith("ON"))
            		    {System.out.println("Light On");//.substring(54, 57));}
            		    this.out1.write('L');
            		    }
                      	
                      	 if(d.startsWith("INFORM"))
             		    {

                 		    this.out1.write('B');
                 		    System.out.println("Informing Others....");//.substring(54, 57));}

                     		try {
                         	    Thread.sleep(6000);
                         	} catch(InterruptedException ex) {
                         	    Thread.currentThread().interrupt();
                         	}
             		   this.out.write('A');
                       this.out.write('T');
                       this.out.write('+');
                       this.out.write('C');
                       this.out.write('M');
                       this.out.write('G');
                       this.out.write('S');
                       this.out.write('=');
                       this.out.write('"');
                       this.out.write('+');
                       this.out.write('9');
                       this.out.write('1');
                       this.out.write('7');
                       this.out.write('4');
                       this.out.write('1');
                       this.out.write('8');
                       this.out.write('8');
                       this.out.write('6');
                       this.out.write('7');
                       this.out.write('1');
                       this.out.write('9');
                       this.out.write('8');
                       this.out.write('"');
                       this.out.write(0X0a);
                       this.out.write(0X0D);

                       this.out.write('A');
                       this.out.write('L');
                       this.out.write('E');
                       this.out.write('R');
                       this.out.write('T');
                       this.out.write('!');
                       this.out.write('!');
                       this.out.write('!');
                       this.out.write(26);

           		    this.out1.write('F');

                    coumt=0;
             		    }
                      	 
                      	 
            		    d=null;
                        }
            		    
            		    
            		    
            }
                
            catch ( IOException e )
            {
                e.printStackTrace();
            }            
        }
            }

                catch ( IOException e )
                {
                    e.printStackTrace();
                }  
        }
    }
    

}


    
    

    /** */
  /*  public static class SerialWriter implements Runnable 
    {
        OutputStream out;
        
        public SerialWriter ( OutputStream out )
        {

            this.out = out;
        }        
           
        public void run ()
        {
            try
            {       
            	TwoWaySerialComm ics = new TwoWaySerialComm("c:\\test1.jpg", "c:\\test2.jpg");
            	ics.compare();

                System.out.println("Image Match com46 === " + ics.match());
                
                int c = 0;
                /*while ( ( c = System.in.read()) > -1 )
                {
                	System.out.println("c value:"+c);
                	if(c=='a'){
                * /		try {
                    	    Thread.sleep(5000);
                    	} catch(InterruptedException ex) {
                    	    Thread.currentThread().interrupt();
                    	}
                    if(ics.match()==false)
                    {
                    	System.out.println("Image Not Regozined");
                        this.out.write('A');
                        this.out.write('T');
                        this.out.write('+');
                        this.out.write('C');
                        this.out.write('M');
                        this.out.write('G');
                        this.out.write('S');
                        this.out.write('=');
                        this.out.write('"');
                        this.out.write('+');
                        this.out.write('9');
                        this.out.write('1');
                      /*  this.out.write('8');
                        this.out.write('0');
                        this.out.write('1');
                        this.out.write('5');
                        this.out.write('3');
                        this.out.write('3');
                        this.out.write('5');
                        this.out.write('4');
                        this.out.write('6');
                        this.out.write('2');/
                        this.out.write('8');
                        this.out.write('0');
                        this.out.write('1');
                        this.out.write('5');
                        this.out.write('7');
                        this.out.write('6');
                        this.out.write('6');
                        this.out.write('6');
                        this.out.write('0');
                        this.out.write('5');
                        this.out.write('"');
                        this.out.write(0X0a);
                        this.out.write(0X0D);

                        this.out.write('A');
                        this.out.write('L');
                        this.out.write('E');
                        this.out.write('R');
                        this.out.write('T');
                        this.out.write('!');
                        this.out.write('!');
                        this.out.write('!');
                        this.out.write(26);
                    }               
            }
            catch ( Exception e )
            {
                e.printStackTrace();
            }            
        }*/
  //  }
//}  
